package haust;


import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.openal.EFX10.*;
import static org.lwjgl.openal.AL11.*;
import static org.lwjgl.openal.AL10.*;

import org.lwjgl.BufferUtils;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;

import java.nio.*;

/**
 * This is a Scene which demonstrates various effects and filters which can be achieved in OpenAL<br/>
 * Keys used: <br/>
 * Q - Stop the source, E - moving source <br/>
 * Z - play continousG_mono.wav, X - hardrain.wav, C - no sounds <br/>
 * 1 - Lowpass + reverb, 2 - lowpass only, 3 - reverb only, 4 - no filter or effect<br/>
 * WASD to move around and hold rightclick to rotate camera<br/>
 * <br/> 
 * <br/>
 * HowTo create an effect in OpenAL. <br/>
 * <br/>
 * Generate EffectSlot (alGenAuxiliaryEffectSlots).  (only for effects as far as I know)  <br/>
 * Generate an effect or filter (alGenEffects or alGenFilters).<br/> 
 * Set filter\effect type ( alFilteri(filterID, AL_FILTER_TYPE, typeOfFilterHere) or alEffecti(effectID, AL_EFFECT_TYPE, typeOfEffect) ).<br/> 
 * Set filter\effect options with alFilterf/alEffectf or alFilteri/alEffecti.<br/>
 * 
 * if it's an effect; bind the effect to an auxiliary slot with alAuxiliaryEffectSloti(slotID,AL_EFFECTSLOT_EFFECT, effectID)
 * filters
 * 
 * Bind the effect or filter with alSource3i or alSourcei respectively
 * 
 */
class SoundScene implements Client
{
	private Camera cam;
	private SoundSource srcRain;
	private SoundSource srcG;
	private SoundSource srcCurrent;
	
	private IntBuffer slot = BufferUtils.createIntBuffer(1);
	private IntBuffer fx = BufferUtils.createIntBuffer(1);
	private IntBuffer filter = BufferUtils.createIntBuffer(1);
	
	private final String STROPTION_1 = "LowPass Filter + Reverb Effect";
	private final String STROPTION_3 = "LowPass Filter only";
	private final String STROPTION_2 = "Reverb Effect only";
	private final String STROPTION_4 = "No effect or filter";
	private String STRPRINT = STROPTION_4;
	
	Vec3 position = new Vec3(0,1,-5.0f);
	Vec3 velocity = new Vec3(0,0,0);
	int curSound = 0;
	
	/**
	 * 
	 */
	@Override
	public int Initialize() {		
		cam = new Camera();
		SoundManager.addSound("hardrain.wav");
		SoundManager.addSound("continousG_mono.wav");
		srcRain = SoundManager.createNewSource("hardrain.wav");
		srcG = SoundManager.createNewSource("continousG_mono.wav");
		
		srcCurrent = srcG;
	
		srcCurrent.setPos(position);
		srcCurrent.setVel(velocity);
		
		alGenAuxiliaryEffectSlots(slot);
		alGenEffects(fx);
		alGenFilters(filter);
		
		alFilteri(filter.get(0), AL_FILTER_TYPE, AL_FILTER_LOWPASS);
		alFilterf(filter.get(0), AL_LOWPASS_GAIN, 0.6f);
		alFilterf(filter.get(0), AL_LOWPASS_GAINHF, 0.6f);
		
		
		alEffecti(fx.get(0), AL_EFFECT_TYPE, AL_EFFECT_REVERB);
		alEffectf(fx.get(0), AL_REVERB_DECAY_TIME, 5.1f);
		
		alAuxiliaryEffectSloti(slot.get(0),AL_EFFECTSLOT_EFFECT, fx.get(0));
		return 0;
	}

	@Override
	public void Deinitialize() {
		SoundManager.removeSource(srcRain);
		SoundManager.removeSource(srcG);
		
		alDeleteAuxiliaryEffectSlots(slot);
		alDeleteFilters(filter);
		alDeleteEffects(fx);
	}

	@Override
	public void Update(float fDelta) {
		if( Mouse.isButtonDown(1) )
		{
			if( Mouse.isGrabbed() == false )
				Mouse.setGrabbed(true);
			else
				cam.rotate(Mouse.getDX(), Mouse.getDY() );
		}
		else if( Mouse.isGrabbed() )
			Mouse.setGrabbed(false);
		
		cam.move( Keyboard.KEY_W,Keyboard.KEY_S, Keyboard.KEY_A, Keyboard.KEY_D );
		
		//both effects
		if( Keyboard.isKeyDown(Keyboard.KEY_1))
		{
			alSource3i(srcG.getSourceID(), AL_AUXILIARY_SEND_FILTER, slot.get(0), 0,  0 );
			alSourcei(srcG.getSourceID(), AL_DIRECT_FILTER, filter.get(0));
			
			alSource3i(srcRain.getSourceID(), AL_AUXILIARY_SEND_FILTER, slot.get(0), 0,  0 );
			alSourcei(srcRain.getSourceID(), AL_DIRECT_FILTER, filter.get(0));
			STRPRINT = STROPTION_1;
		}
		//reverb only
		else if( Keyboard.isKeyDown(Keyboard.KEY_2) )
		{
			alSource3i(srcG.getSourceID(), AL_AUXILIARY_SEND_FILTER, slot.get(0), 0,  0 );
			alSourcei(srcG.getSourceID(), AL_DIRECT_FILTER, AL_FILTER_NULL);
			
			alSource3i(srcRain.getSourceID(), AL_AUXILIARY_SEND_FILTER, slot.get(0), 0,  0 );
			alSourcei(srcRain.getSourceID(), AL_DIRECT_FILTER, AL_FILTER_NULL);
			STRPRINT = STROPTION_2;
		}
		//lowpass only
		else if( Keyboard.isKeyDown(Keyboard.KEY_3) )
		{
			alSource3i(srcG.getSourceID(), AL_AUXILIARY_SEND_FILTER,AL_EFFECT_NULL, 0,  AL_FILTER_NULL );
			alSourcei(srcG.getSourceID(), AL_DIRECT_FILTER, filter.get(0));
			
			alSource3i(srcRain.getSourceID(), AL_AUXILIARY_SEND_FILTER,AL_EFFECT_NULL, 0,  AL_FILTER_NULL );
			alSourcei(srcRain.getSourceID(), AL_DIRECT_FILTER, filter.get(0));
			STRPRINT = STROPTION_3;
		}
		//no effect
		else if( Keyboard.isKeyDown(Keyboard.KEY_4) )
		{
			alSource3i(srcG.getSourceID(), AL_AUXILIARY_SEND_FILTER,AL_EFFECT_NULL, 0,  AL_FILTER_NULL );
			alSourcei(srcG.getSourceID(), AL_DIRECT_FILTER, AL_FILTER_NULL);
			
			alSource3i(srcRain.getSourceID(), AL_AUXILIARY_SEND_FILTER,AL_EFFECT_NULL, 0,  AL_FILTER_NULL );
			alSourcei(srcRain.getSourceID(), AL_DIRECT_FILTER, AL_FILTER_NULL);
			STRPRINT = STROPTION_4;
		}
		
		if( Keyboard.isKeyDown(Keyboard.KEY_Q) )
		{
			velocity.setX(0);
			position.setX(0);
			position.setY(1);
			position.setZ(-5);
		}
		else if( Keyboard.isKeyDown(Keyboard.KEY_E) )
		{
			velocity.setX(-25);
		}
		
		
		//Toggling which sound to play
		if( Keyboard.isKeyDown(Keyboard.KEY_Z)) //continousG 
		{
			if( curSound != 1 )
			{
				alSourceStop(srcCurrent.getSourceID());
				srcCurrent = srcG;
				alSourcePlay(srcCurrent.getSourceID());
				curSound = 1;
			}			
		}
		else if( Keyboard.isKeyDown(Keyboard.KEY_X)) //rain
		{
			if( curSound != 2 )
			{
				alSourceStop(srcCurrent.getSourceID());
				srcCurrent = srcRain;
				alSourcePlay(srcCurrent.getSourceID());
				curSound = 2;
			}
		}
		else if( Keyboard.isKeyDown(Keyboard.KEY_C)) //none
		{
			if( curSound != 0 )
			{
				alSourceStop(srcCurrent.getSourceID());
				curSound = 0;
			}			
		}
		
		
		position.setX(   position.getX() + velocity.getX() * fDelta );
		if( Math.abs( position.getX() ) > 50.0f )
			velocity.setX( velocity.getX() * -1 );
		
		srcCurrent.setVel(velocity);
		srcCurrent.setPos(position);
		srcCurrent.update();
	}

	@Override
	public void Render() {
		cam.lookAt();
		
		glColor3f(1,1,1);
	    glBegin(GL_LINES);
		float s = 50.0f;
	    for( float val = -s; val <= s; val+=1.0f)
	    {
	    	glVertex3f(val, 0.1f, -s);
	    	glVertex3f(val, 0.1f,  s);
	    	
	    	glVertex3f(-s, 0.1f, val);
	    	glVertex3f( s, 0.1f, val);
	    }
	    glEnd();
	    
	    glPointSize(3.0f);
	    glColor3f(1,0,0);
	    glBegin(GL_POINTS);
	    	glVertex3f(position.getX(), position.getY(), position.getZ());
	    glEnd();
	    
	    Entry.pushOrtho();
	    	if( STRPRINT != null )
	    		FontManager.drawTextFont(STRPRINT, 28,Display.getHeight());
	    Entry.popOrtho();
	}

	@Override
	public int getRenderMode() {
		return 0;
	}

	@Override
	public boolean getExitFlag() {
		return Keyboard.isKeyDown(Keyboard.KEY_ESCAPE);
	}
	
}